<!DOCTYPE html>
<!-- saved from url=(0058)https://online.pragmaticstudio.com/courses/elixir/steps/55 -->
<html lang="en-US" class="book"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  
  <title>The Pragmatic Studio Online | Developing with Elixir/OTP</title>
  <link rel="apple-touch-icon-precomposed" sizes="144x144" href="https://online.pragmaticstudio.com/favicons/apple-touch-icon-144x144.png">
  <link rel="apple-touch-icon-precomposed" sizes="152x152" href="https://online.pragmaticstudio.com/favicons/apple-touch-icon-152x152.png">
  <link rel="icon" type="image/png" href="https://online.pragmaticstudio.com/favicons/favicon-32x32.png" sizes="32x32">
  <link rel="icon" type="image/png" href="https://online.pragmaticstudio.com/favicons/favicon-16x16.png" sizes="16x16">
  <link rel="shortcut icon" href="https://online.pragmaticstudio.com/favicons/favicon.ico">
  <link rel="stylesheet" media="all" href="./25The Pragmatic Studio Online _ Developing with Elixir_OTP_files/application-cb185c07f9e7cf3071c019ec9ae89c92.css">
  <script async="" src="./25The Pragmatic Studio Online _ Developing with Elixir_OTP_files/analytics.js.завантаження"></script><script src="./25The Pragmatic Studio Online _ Developing with Elixir_OTP_files/application-dc521b896b294cf4648f0cd28001e154.js.завантаження"></script>
  
  <meta name="csrf-param" content="authenticity_token">
<meta name="csrf-token" content="mVPooxw77S1xnxREdQl6zCQKkgSSij8hpMiuKy81f3HyWs3x7Fer57wV+GGPt1PBkzh/sJijRukN9FrrgAJKaQ==">
    <script type="text/javascript">
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-59927351-1', 'auto');
  ga('send', 'pageview');
</script>

</head>
<body>
  <div id="header">
    <div id="logo">
      <a title="Pragmatic Studio Online" href="https://online.pragmaticstudio.com/"><img alt="Pragmatic Studio Online" title="Pragmatic Studio Online" src="./25The Pragmatic Studio Online _ Developing with Elixir_OTP_files/logo-a167560d29b6afb905c24a3432045f34.png"></a>
    </div>
    <div id="site_links">
      <ul>
        <li>
          <a href="https://pragmaticstudio.com/my_account">my courses</a>
        </li>
        <li>•</li>
        <li>
          <a href="https://online.pragmaticstudio.com/signout">sign out</a>
        </li>
      </ul>
    </div>
  </div>
  <div id="main_wrapper_1">
    <div id="main_wrapper_2">
      <div id="main_wrapper_3">
        <div id="main">
          <div id="content">
            

<h1>Refactoring Toward GenServer</h1>
<h2 class="subtitle">Notes</h2>

<h3>Exercise: Refactor the FourOhFourCounter</h3>
<p>
  In the previous exercise you built a <tt>FourOhFourCounter</tt> that keeps track of the number of times a particular path has resulted in a 404. If you want some extra practice leading up to a <tt>GenServer</tt>, refactor your <tt>FourOhFourCounter</tt> so that it has a generic listen loop like we did in the video. 
</p>
<p>
  Try doing it from memory before looking at the answer for guidance. Work through any errors you get... and learn from them! Once you get it working, color outside the lines—introduce a new message, try a different style, or even break something—and use the feedback to learn even more. <strong>Understanding how this generic server works will put you in a better position to understand GenServers in the next section of the course.</strong>
</p>
<p>
  For bonus points, you can also implement the <tt>call</tt> and <tt>cast</tt> helper functions. As a simple example of a <tt>cast</tt> message, introduce a message that resets the state.
</p>
<p>
  Start by changing the existing <tt>listen_loop</tt> function in the  
  <tt>FourOhFourCounter</tt> so that all the generic and application-specific code lives in that one module.
</p>
      <div class="toggle">
                <p>
          <a class="button show-hide" href="javascript:void(0)" rel="nofollow">
            <span class="title">Show Answer</span>
          </a>
        </p>
      <p style="display:none;">
        <a class="button show-hide" href="javascript:void(0)" rel="nofollow">
          <span class="title">Hide Answer</span>
        </a>
      </p>

        <div style="display:none;">
          
          <div class="highlight"><pre><span class="kd">defmodule</span> <span class="nc">Servy.FourOhFourCounter</span> <span class="k">do</span>

  <span class="na">@name</span> <span class="ss">:four_oh_four_counter</span>

  <span class="c1"># Client Interface</span>

  <span class="kd">def</span> <span class="n">start</span> <span class="k">do</span>
    <span class="nc">IO</span><span class="p">.</span><span class="n">puts</span> <span class="s2">"Starting the 404 counter..."</span>
    <span class="n">pid</span> <span class="p">=</span> <span class="n">spawn</span><span class="p">(</span><span class="bp">__MODULE__</span><span class="p">,</span> <span class="ss">:listen_loop</span><span class="p">,</span> <span class="p">[%{}])</span>  
    <span class="nc">Process</span><span class="p">.</span><span class="n">register</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="na">@name</span><span class="p">)</span>
    <span class="n">pid</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">bump_count</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">call</span> <span class="na">@name</span><span class="p">,</span> <span class="p">{</span><span class="ss">:bump_count</span><span class="p">,</span> <span class="n">path</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">get_counts</span> <span class="k">do</span>
    <span class="n">call</span> <span class="na">@name</span><span class="p">,</span> <span class="ss">:get_counts</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">get_count</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">call</span> <span class="na">@name</span><span class="p">,</span> <span class="p">{</span><span class="ss">:get_count</span><span class="p">,</span> <span class="n">path</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">reset</span> <span class="k">do</span>
    <span class="n">cast</span> <span class="na">@name</span><span class="p">,</span> <span class="ss">:reset</span>
  <span class="k">end</span>

  <span class="c1"># Helper Functions</span>

  <span class="kd">def</span> <span class="n">call</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">message</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">send</span> <span class="n">pid</span><span class="p">,</span> <span class="p">{</span><span class="ss">:call</span><span class="p">,</span> <span class="n">self</span><span class="p">(),</span> <span class="n">message</span><span class="p">}</span>

    <span class="k">receive</span> <span class="k">do</span> <span class="p">{</span><span class="ss">:response</span><span class="p">,</span> <span class="n">response</span><span class="p">}</span> <span class="p">-&gt;</span> <span class="n">response</span> <span class="k">end</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">cast</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">message</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">send</span> <span class="n">pid</span><span class="p">,</span> <span class="p">{</span><span class="ss">:cast</span><span class="p">,</span> <span class="n">message</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="c1"># Server</span>

  <span class="kd">def</span> <span class="n">listen_loop</span><span class="p">(</span><span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="k">receive</span> <span class="k">do</span>
      <span class="p">{</span><span class="ss">:call</span><span class="p">,</span> <span class="n">sender</span><span class="p">,</span> <span class="n">message</span><span class="p">}</span> <span class="ow">when</span> <span class="n">is_pid</span><span class="p">(</span><span class="n">sender</span><span class="p">)</span> <span class="p">-&gt;</span>
        <span class="p">{</span><span class="n">response</span><span class="p">,</span> <span class="n">new_state</span><span class="p">}</span> <span class="p">=</span> <span class="n">handle_call</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span>
        <span class="n">send</span> <span class="n">sender</span><span class="p">,</span> <span class="p">{</span><span class="ss">:response</span><span class="p">,</span> <span class="n">response</span><span class="p">}</span>
        <span class="n">listen_loop</span><span class="p">(</span><span class="n">new_state</span><span class="p">)</span>
      <span class="p">{</span><span class="ss">:cast</span><span class="p">,</span> <span class="n">message</span><span class="p">}</span> <span class="p">-&gt;</span>
        <span class="n">new_state</span> <span class="p">=</span> <span class="n">handle_cast</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span>
        <span class="n">listen_loop</span><span class="p">(</span><span class="n">new_state</span><span class="p">)</span>
      <span class="n">unexpected</span> <span class="p">-&gt;</span>
        <span class="nc">IO</span><span class="p">.</span><span class="n">puts</span> <span class="s2">"Unexpected messaged: </span><span class="si">#{</span><span class="n">inspect</span> <span class="n">unexpected</span><span class="si">}</span><span class="s2">"</span>
        <span class="n">listen_loop</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">handle_call</span><span class="p">({</span><span class="ss">:bump_count</span><span class="p">,</span> <span class="n">path</span><span class="p">},</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">new_state</span> <span class="p">=</span> <span class="nc">Map</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">(</span><span class="ni">&amp;1</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
    <span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="n">new_state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">handle_call</span><span class="p">(</span><span class="ss">:get_counts</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="p">{</span><span class="n">state</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">handle_call</span><span class="p">({</span><span class="ss">:get_count</span><span class="p">,</span> <span class="n">path</span><span class="p">},</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">count</span> <span class="p">=</span> <span class="nc">Map</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
    <span class="p">{</span><span class="n">count</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">handle_cast</span><span class="p">(</span><span class="ss">:reset</span><span class="p">,</span> <span class="n">_state</span><span class="p">)</span> <span class="k">do</span>
    <span class="p">%{}</span>
  <span class="k">end</span>
<span class="k">end</span>
</pre></div>
        </div>
      </div>

<p>
  Then move the <tt>listen_loop</tt> and the other generic code to a <tt>GenericServer</tt> module.
</p>
      <div class="toggle">
                <p>
          <a class="button show-hide" href="javascript:void(0)" rel="nofollow">
            <span class="title">Show Answer</span>
          </a>
        </p>
      <p style="display:none;">
        <a class="button show-hide" href="javascript:void(0)" rel="nofollow">
          <span class="title">Hide Answer</span>
        </a>
      </p>

        <div style="display:none;">
          
          <div class="highlight"><pre><span class="kd">defmodule</span> <span class="nc">Servy.GenericServer</span> <span class="k">do</span>
  <span class="kd">def</span> <span class="n">start</span><span class="p">(</span><span class="n">callback_module</span><span class="p">,</span> <span class="n">initial_state</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">pid</span> <span class="p">=</span> <span class="n">spawn</span><span class="p">(</span><span class="bp">__MODULE__</span><span class="p">,</span> <span class="ss">:listen_loop</span><span class="p">,</span> <span class="p">[</span><span class="n">initial_state</span><span class="p">,</span> <span class="n">callback_module</span><span class="p">])</span>
    <span class="nc">Process</span><span class="p">.</span><span class="n">register</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
    <span class="n">pid</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">call</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">message</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">send</span> <span class="n">pid</span><span class="p">,</span> <span class="p">{</span><span class="ss">:call</span><span class="p">,</span> <span class="n">self</span><span class="p">(),</span> <span class="n">message</span><span class="p">}</span>

    <span class="k">receive</span> <span class="k">do</span> <span class="p">{</span><span class="ss">:response</span><span class="p">,</span> <span class="n">response</span><span class="p">}</span> <span class="p">-&gt;</span> <span class="n">response</span> <span class="k">end</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">cast</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">message</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">send</span> <span class="n">pid</span><span class="p">,</span> <span class="p">{</span><span class="ss">:cast</span><span class="p">,</span> <span class="n">message</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">listen_loop</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">callback_module</span><span class="p">)</span> <span class="k">do</span>
    <span class="k">receive</span> <span class="k">do</span>
      <span class="p">{</span><span class="ss">:call</span><span class="p">,</span> <span class="n">sender</span><span class="p">,</span> <span class="n">message</span><span class="p">}</span> <span class="ow">when</span> <span class="n">is_pid</span><span class="p">(</span><span class="n">sender</span><span class="p">)</span> <span class="p">-&gt;</span>
        <span class="p">{</span><span class="n">response</span><span class="p">,</span> <span class="n">new_state</span><span class="p">}</span> <span class="p">=</span> <span class="n">callback_module</span><span class="p">.</span><span class="n">handle_call</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span>
        <span class="n">send</span> <span class="n">sender</span><span class="p">,</span> <span class="p">{</span><span class="ss">:response</span><span class="p">,</span> <span class="n">response</span><span class="p">}</span>
        <span class="n">listen_loop</span><span class="p">(</span><span class="n">new_state</span><span class="p">,</span> <span class="n">callback_module</span><span class="p">)</span>
      <span class="p">{</span><span class="ss">:cast</span><span class="p">,</span> <span class="n">message</span><span class="p">}</span> <span class="p">-&gt;</span>
        <span class="n">new_state</span> <span class="p">=</span> <span class="n">callback_module</span><span class="p">.</span><span class="n">handle_cast</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span>
        <span class="n">listen_loop</span><span class="p">(</span><span class="n">new_state</span><span class="p">,</span> <span class="n">callback_module</span><span class="p">)</span>
      <span class="n">unexpected</span> <span class="p">-&gt;</span>
        <span class="nc">IO</span><span class="p">.</span><span class="n">puts</span> <span class="s2">"Unexpected messaged: </span><span class="si">#{</span><span class="n">inspect</span> <span class="n">unexpected</span><span class="si">}</span><span class="s2">"</span>
        <span class="n">listen_loop</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">callback_module</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="kd">defmodule</span> <span class="nc">Servy.FourOhFourCounter</span> <span class="k">do</span>

  <span class="na">@name</span> <span class="ss">:four_oh_four_counter</span>

  <span class="kn">alias</span> <span class="nc">Servy.GenericServer</span>

  <span class="c1"># Client Interface</span>

  <span class="kd">def</span> <span class="n">start</span> <span class="k">do</span>
    <span class="nc">IO</span><span class="p">.</span><span class="n">puts</span> <span class="s2">"Starting the 404 counter..."</span>
    <span class="nc">GenericServer</span><span class="p">.</span><span class="n">start</span><span class="p">(</span><span class="bp">__MODULE__</span><span class="p">,</span> <span class="p">%{},</span> <span class="na">@name</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">bump_count</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="k">do</span>
    <span class="nc">GenericServer</span><span class="p">.</span><span class="n">call</span> <span class="na">@name</span><span class="p">,</span> <span class="p">{</span><span class="ss">:bump_count</span><span class="p">,</span> <span class="n">path</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">get_counts</span> <span class="k">do</span>
    <span class="nc">GenericServer</span><span class="p">.</span><span class="n">call</span> <span class="na">@name</span><span class="p">,</span> <span class="ss">:get_counts</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">get_count</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="k">do</span>
    <span class="nc">GenericServer</span><span class="p">.</span><span class="n">call</span> <span class="na">@name</span><span class="p">,</span> <span class="p">{</span><span class="ss">:get_count</span><span class="p">,</span> <span class="n">path</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">reset</span> <span class="k">do</span>
    <span class="nc">GenericServer</span><span class="p">.</span><span class="n">cast</span> <span class="na">@name</span><span class="p">,</span> <span class="ss">:reset</span>
  <span class="k">end</span>

  <span class="c1"># Server Callbacks</span>

  <span class="kd">def</span> <span class="n">handle_call</span><span class="p">({</span><span class="ss">:bump_count</span><span class="p">,</span> <span class="n">path</span><span class="p">},</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">new_state</span> <span class="p">=</span> <span class="nc">Map</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">(</span><span class="ni">&amp;1</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
    <span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="n">new_state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">handle_call</span><span class="p">(</span><span class="ss">:get_counts</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="p">{</span><span class="n">state</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">handle_call</span><span class="p">({</span><span class="ss">:get_count</span><span class="p">,</span> <span class="n">path</span><span class="p">},</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">count</span> <span class="p">=</span> <span class="nc">Map</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
    <span class="p">{</span><span class="n">count</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="kd">def</span> <span class="n">handle_cast</span><span class="p">(</span><span class="ss">:reset</span><span class="p">,</span> <span class="n">_state</span><span class="p">)</span> <span class="k">do</span>
    <span class="p">%{}</span>
  <span class="k">end</span>
<span class="k">end</span>
</pre></div>
        </div>
      </div>


<h3>Code So Far</h3>
<p>
  The code for this video is in the
<code>refactor-server</code> directory found within the
  <tt>video-code</tt> directory of the <a href="https://s3.amazonaws.com/pragmaticstudio/courses/elixir/pragstudio-elixir-code.zip">code bundle</a>.
</p>



<div class="chapter_navigation bottom">
  
    <a class="multi-line-button green" href="https://online.pragmaticstudio.com/courses/elixir/steps/738/achievements" data-method="post" rel="nofollow" style="width:16em">
      <span class="title">Go To Next Video</span>
      <span class="subtitle">and mark this step complete!</span>
    </a>
    
</div>



  



            <div id="footer">
              <p>
  All course material, including videos, slides, and source code, is copyrighted and licensed for
  <em>individual use only</em>. You may make copies for your own personal use (e.g. on your laptop, on your
  iPad, on your backup drive). However, you may not transfer ownership or share the material with other
  people. We make no guarantees that the source code is fit for any purpose. Course material may not be
  used to create training material, courses, books, and the like. Please support us and our instructors by
  encouraging others to purchase their own copies. Thank you!
</p>

              <p>
                Copyright © 2005–2018, The Pragmatic Studio.
                All Rights Reserved.
              </p>
            </div>
          </div>
          <div id="sidebar">
            <div class="course_head">
  <h3>Developing with Elixir/OTP</h3>
  <h4 class="subtitle"></h4>
</div>
<div class="progress">
  <div class="meter">
    <div class="meter_progress" style="width: 0%"></div>
  </div>
  <div class="meter_label">
    0% complete
  </div>
  <div class="meter_reset">
    
  </div>
</div>
<div class="navigation">
  <ul>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/1">1. Introduction</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/1">Video</a><span class="time">1:56</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/2">Setup</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/2">2. Create Mix Project</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/3">Video</a><span class="time">8:21</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/4">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/3">3. High-Level Transformations</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/5">Video</a><span class="time">8:27</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/6">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/4">4. Parse Request Line</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/7">Video</a><span class="time">10:21</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/8">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/5">5. Route and Response</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/9">Video</a><span class="time">6:40</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/10">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/6">6. Function Clauses</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/11">Video</a><span class="time">6:28</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/12">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/7">7. Request Params and Status Codes</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/13">Video</a><span class="time">8:45</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/14">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/8">8. Rewrite Paths and Track 404s</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/15">Video</a><span class="time">9:31</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/16">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/9">9. Serve Static Files</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/17">Video</a><span class="time">11:27</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/18">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/10">10. Module Attributes</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/19">Video</a><span class="time">3:00</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/20">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/11">11. Organizing Code</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/21">Video</a><span class="time">6:30</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/22">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/12">12. Modeling With Structs</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/23">Video</a><span class="time">11:09</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/24">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/13">13. Handle POST Requests</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/25">Video</a><span class="time">10:32</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/26">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/14">14. Recursion</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/27">Video</a><span class="time">13:17</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/28">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/15">15. Slicing and Dicing with Enum</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/29">Video: Part 1</a><span class="time">10:25</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/30">Video: Part 2</a><span class="time">11:51</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/31">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/16">16. Comprehensions</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/32">Video</a><span class="time">11:15</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/33">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/17">17. A Peek At Phoenix</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/34">Video</a><span class="time">13:12</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/35">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/18">18. Test Automation</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/36">Video</a><span class="time">15:21</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/37">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/19">19. Rendering JSON</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/38">Video</a><span class="time">06:47</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/39">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/20">20. Web Server Sockets</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/40">Video</a><span class="time">19:11</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/41">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/21">21. Concurrent, Isolated Processes</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/42">Video: Part 1</a><span class="time">12:07</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/43">Video: Part 2</a><span class="time">10:21</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/44">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/22">22. Sending and Receiving Messages</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/45">Video</a><span class="time">19:38</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/46">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/23">23. Asynchronous Tasks</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/47">Video</a><span class="time">20:19</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/48">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/24">24. Stateful Server Processes</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/49">Video: Part 1</a><span class="time">8:09</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/50">Video: Part 2</a><span class="time">11:55</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/51">Video: Part 3</a><span class="time">9:49</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/52">Video: Part 4</a><span class="time">8:59</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/53">Notes</a></li>
        </ul>
      </li>
      <li class="expanded">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/25">25. Refactoring Toward GenServer</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/54">Video</a><span class="time">21:12</span></li>
            <li class="here"><a href="https://online.pragmaticstudio.com/courses/elixir/steps/55">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/26">26. OTP GenServer</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/56">Video</a><span class="time">16:57</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/57">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/27">27. Another GenServer</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/58">Video</a><span class="time">9:00</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/59">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/28">28. Linking Processes</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/60">Video</a><span class="time">13:38</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/61">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/29">29. Fault Recovery with OTP Supervisors</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/62">Video: Part 1</a><span class="time">13:39</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/63">Video: Part 2</a><span class="time">6:13</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/64">Notes</a></li>
        </ul>
      </li>
      <li class="">
        <a href="https://online.pragmaticstudio.com/courses/elixir/modules/30">30. Final OTP Application</a>
        <ul>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/65">Video</a><span class="time">15:22</span></li>
            <li class=""><a href="https://online.pragmaticstudio.com/courses/elixir/steps/66">Notes</a></li>
            <li class="not-completable"><a href="https://online.pragmaticstudio.com/courses/elixir/next_steps">Next Steps</a></li>
            <li class="not-completable"><a href="https://online.pragmaticstudio.com/courses/elixir/evaluation">Evaluation</a></li>
        </ul>
      </li>
  </ul>
</div>


          </div>
        </div>
      </div>
    </div>
  </div>


<script id="wappalyzer" src="chrome-extension://gppongmhjkpfnbhagpmjfkannfbllamg/js/inject.js"></script></body></html>